/*
 * 24-abr-2007 
 */
package futbol.tacticas.concursantes2007.Chuky.chuky.futbolista;

import java.awt.Point;
import java.util.ArrayList;

import futbol.General;
import futbol.tacticas.concursantes2007.Chuky.chuky.entrenador.Anotacion;

/**
 *
 * @author Joan Crosas
 */
public class AnalizadorPases {
	private Futbolista futbolista;
	private ArrayList<Futbolista> amigos;
	private ArrayList<Pase> pases;
	private ArrayList<Pase> pasesSinFiltrar;

	/**
	 * 
	 */
	public AnalizadorPases( Futbolista futbolista, ArrayList<Futbolista> amigos ) {
		this.futbolista = futbolista;
		this.amigos = amigos;
	}
	
	
	public void analizar() {
		
		pases = new ArrayList<Pase>();
		pasesSinFiltrar = new ArrayList<Pase>();
		
		Point posFutbolista = futbolista.getPosicion();
		
		for( int i = 0; i < amigos.size(); i++ ) {
			Futbolista amigo = amigos.get( i );
			Point posAmigo = amigo.getPosicion();
			
			// miramos que el futbolista no sea el mismo o algun defensa y que no est demasiado lejos
			if( futbolista != amigo && amigo.getNumero() != 0 && amigo.getNumero() != 1 && amigo.getNumero() != 2 && posFutbolista.distance( posAmigo ) < futbolista.getDistanciaMaxPase() ) {			
				pases.addAll( evaluarPase( amigo ) );
			}
		}
		
		ordenarPases();
		
		pasesSinFiltrar.addAll( pases );
	}
	
	private ArrayList<Pase> evaluarPase( Futbolista amigo ) {
		Point posAmigo = amigo.getPosicion();
		ArrayList<Pase> pases = new ArrayList<Pase>();
		
		Point posFutbolista = futbolista.getPosicion();
		
		double alfaAmigo = General.getAngulo( posFutbolista.x, posFutbolista.y, posAmigo.x, posAmigo.y );
		double alfa = alfaAmigo;
		while( alfaAmigo - alfa < Math.PI / 3 ) {
			Pase pase = evaularAnguloPase( amigo, General.corregirAngulo( alfaAmigo ) );
			if( pase != null ) {
				pases.add( pase );
			}
			alfaAmigo = alfaAmigo + Math.PI / 18;
		}
		
		alfaAmigo = alfa - Math.PI / 18;
		while( alfa - alfaAmigo < Math.PI / 3 ) {
			Pase pase = evaularAnguloPase( amigo, General.corregirAngulo( alfaAmigo ) );
			if( pase != null ) {
				pases.add( pase );
			}
			alfaAmigo = alfaAmigo - Math.PI / 18;
		}
		
		return pases;
	}
	
	private Pase evaularAnguloPase( Futbolista amigo, double angulo ) {
		ArrayList<InfoPosicion> infoPosiciones = new ArrayList<InfoPosicion>();
		
		// creamos un baln ficticio
		Balon balon = new Balon( futbolista.getPosicion(), angulo, futbolista.getFuerza()*3 );
		
		int t = 0; // instantes de tiempo transcurridos
		Point posBalonAnterior;
		Point posBalon = balon.getPosicionBalon();
		double distanciaBalon = 0;
		double distanciaAmigo = 0;
		
		/*
		 * repetimos hasta que pasamos cerca de nuestro amigo
		 * pero sin pasarse de la distancia maxima de pase
		 */
		 while( posBalon.distance( amigo.getPosicion() ) > distanciaAmigo + 10 && distanciaBalon < futbolista.getDistanciaMaxPase() && t < 20 ) {
			
			t++;
			posBalonAnterior = posBalon;
			posBalon = balon.getPosicionFutura( t );
			
			distanciaBalon += posBalon.distance( posBalonAnterior ); // distancia que ha recorrido el bal
			int tFutbolista = t;
			distanciaAmigo = amigo.getDistanciaFutbolista( tFutbolista );
			
			if( balon.getVelocidadBalon() - t < 15 ) {
				InfoPosicion infoPos = new InfoPosicion( posBalon, futbolista.getPosicionAmigos(), futbolista.getPosicionEnemigos() );
				infoPosiciones.add( infoPos );
			}
			
		}
		
		// miramos si el pase es bueno
		Pase pase = null;
		if( infoPosiciones.size() > 0 ) {
			InfoPase info = new InfoPase( infoPosiciones );
			
			Anotacion anotacion = new Anotacion();
			anotacion.setFutbolista( amigo );
			anotacion.setAccion( Anotacion.ACCION_CORRER );
			anotacion.setDonde( posBalon );
			
			pase = new Pase();
			pase.setFutbolista( amigo );
			pase.setAngulo( angulo );
			pase.setDistancia( distanciaBalon );
			pase.setInfo( info );
			pase.setAnotacion( anotacion );
		}
	
		
		return pase;		
	}
	
	public void filtrarPases( boolean pasesAtras ) {
		ArrayList<Pase> pasesFiltrados = new ArrayList<Pase>();
		
		for( int i = 0; i < pases.size(); i++ ) {
			/*
			 * unicamente analizaremos los pases mas buenos dependiendo del estado del futbolista
			 * si el futbolista est en buen estado (no tiene a ningn enemigo cerca) obtendremos
			 * los mejores pases, si el futbolista est en mal estado seremos mas permisivos con el 
			 * filtro (nos interesa quitarnos el baln de encima) 
			 */
			if( pases.get( i ).getInfo().getMalo() <= futbolista.getInfoPosicion().getMalo() ) {
				double angulo = pases.get( i ).getAngulo();
				if( pasesAtras || angulo < Math.PI / 2 || angulo > 3 * Math.PI / 2 ) {
					pasesFiltrados.add( pases.get( i ) );
				}
			}
		}
		
		pases = pasesFiltrados;
	}
	
	/**
	 * Ordena los pases dependiendo del angulo
	 * @param pases
	 * @return
	 */
	private void ordenarPases() {
		ArrayList<Pase> pasesOrdenados = new ArrayList<Pase>();
		
		for( int i = 0; i < pases.size(); i++ ) {
			int indice = 0;
			for( int j = 0; j < pasesOrdenados.size(); j++ ) {
				double angulo = pases.get( i ).getAngulo();
				double anguloOrdenado = pasesOrdenados.get( j ).getAngulo();
				
				if( angulo > Math.PI ) {
					angulo = 2 * Math.PI - angulo;
				}
				if( anguloOrdenado > Math.PI ) {
					anguloOrdenado = 2 * Math.PI - anguloOrdenado;
				}
				
				if( angulo < anguloOrdenado ) {
					indice = j;
				}
			}
			pasesOrdenados.add( indice, pases.get( i ) );			
		}
		
		pases = pasesOrdenados;
	}
	
	public ArrayList<Pase> getPases() {
		return pases;
	}
	
	/**
	 * Analiza el coste a meta
	 * @return Devuelve el pase que de como resultado el mnimo coste a meta
	 */
	public Pase getMejorPase() {
		Pase mejorPase = null;
		int costeMejorPase = 9000;
		
		for( int i = 0; i < pases.size(); i++ ) {
			Pase paseAmigo = pases.get( i );
			
			if( paseAmigo.getInfo().getMuyMalo() < 10 ) {
				/*
				 * AnalizadorCamino analizadorCamino = new AnalizadorCamino( getPosicion(), getPosicionAmigos()[9], getPosicionEnemigos() );
					Camino camino10 = analizadorCamino.analizar();
				 */
				AnalizadorCamino analizadorCamino = new AnalizadorCamino( paseAmigo.getFutbolista().getPosicion(), new Point( 160, 0 ), paseAmigo.getFutbolista().getPosicionEnemigos() );
				int costeAmigo = analizadorCamino.analizar().getCoste();
				if( mejorPase == null ) {
					mejorPase = paseAmigo;
				} else {
					if( costeAmigo < costeMejorPase ) {
						mejorPase = paseAmigo;
						costeMejorPase = costeAmigo;
					}
				}
			}
		}
		
		return mejorPase;
	}
	
	/**
	 * bueno - malo
	 * @return Devuelve el pase donde haya menos enemigos y mas amigos
	 */
	public Pase getPaseMenosMalo() {
		Pase mejorPase = null;
		for( int i = 0; i < pasesSinFiltrar.size(); i++ ) {
			Pase pase = pasesSinFiltrar.get( i );

			// siempre hacia delante
			if( pase.getAngulo() < Math.PI / 2 || pase.getAngulo() > 3 * Math.PI / 2 ) {
				if( mejorPase == null ) {
					mejorPase = pase;
				} else {
					int puntuacionMejorPase = mejorPase.getInfo().getBueno() - mejorPase.getInfo().getMalo();
					int puntuacionPase = pase.getInfo().getBueno() - pase.getInfo().getMalo();
					if( puntuacionPase > puntuacionMejorPase ) {
						mejorPase = pase;
					}
					
				}
			}
		}
		return mejorPase;
	}

}
 